Terraform으로 EC2를 구축해보기
안녕하세요. 클래스메소드의 서은우입니다.
Terraform 을 사용해 AWS 리소스를 구축해보았습니다.
시작하기에 앞서
생성할 리소스
Terraform 으로 Public Subnet에 위치한 EC2 인스턴스를 생성합니다.
파일 구조
작성한 Terraform 파일의 구조는 다음과 같습니다.
- main.tf
- Provider 를 정의
- aws.tf
- 생성할 AWS 리소스를 정의
- variables.tf
- aws.tf 파일에서 사용할 변수와 값을 정의
Terraform 사용을 위한 IAM Role 설정
Terraform을 이용해 AWS 리소스를 생성하기 위해서는 적절한 권한이 부여되어 있는 IAM 유저 혹은 역할이 필요합니다.
Terraform 배포를 위해 권한이 부여되어 있는 IAM User 를 사용하는 것도 가능하지만,
필요한 권한을 임시로 얻을 수 있는 AssumeRole을 사용하도록 하겠습니다.
Assume Role 에 대해서는 Terraform 의 aws_caller_identity 를 main.tf 파일에 작성하여 구현하도록 하겠습니다.
Terraform 작성
main.tf
# main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "< 5.71.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
# Assume Role 대상 role의 ARN
assume_role {
role_arn = "arn:aws:iam::<AWS_ACCOUNT>:role/terraform_role"
}
}
data "aws_caller_identity" "current" {}
provider 블록에서는 리소스를 생성할 리전과 assume_role 을 하기 위한 대상 role의 ARN 을 지정해줍니다.
aws_caller_identity 는 지정된 계정의 ID를 참조하는 데이터 소스로 파라메터에 current를 지정하여 현재 계정 정보를 참조할 수 있습니다.
초기화
main.tf 파일을 작성하고 프로바이더에 대한 정의가 완료되었으면 terraform init 명령어로 테라폼을 초기화합니다.
초기화 작업은 한 번이 아니라, 이후에 프로바이더에 변경이 있을 경우에도 실행해주어야합니다.
terraform init
...
Terraform has been successfully initialized!
variables.tf
variables.tf 파일에서는 aws.tf 파일에서 사용할 변수들을 선언합니다.
이곳에서 선언한 변수들은 aws.tf 파일에서 var.변수명의 형식으로 사용하는 것이 가능합니다.
variable "vpc_cidr" {
description = "VPC CIDR block"
type = string
default = "192.168.0.0/16"
}
variable "public_subnet_cidr" {
description = "Public subnet CIDR block"
type = string
default = "192.168.0.0/24"
}
variable "az_1a" {
description = "Availability zone ap-northeast-1a"
type = string
default = "ap-northeast-1a"
}
variable "ec2_type" {
description = "EC2 Insatance Type"
type = string
default = "t3.micro"
}
variable "ami" {
description = "EC2 AMI"
type = string
default = "ami-08ce76bae392de7dc"
}
aws.tf
해당 파일에는 생성한 리소스들을 정의합니다.
# IAM Role(EC2 인스턴스 프로파일용)
resource "aws_iam_role" "ssm_role" {
name = "ec2_ssm_role"
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Action = "sts:AssumeRole",
Effect = "Allow",
Principal = {
Service = "ec2.amazonaws.com"
}
}
]
})
}
resource "aws_iam_role_policy_attachment" "ssm_attach" {
role = aws_iam_role.ssm_role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}
# VPC
resource "aws_vpc" "vpc" {
# var.xxx 의 경우, variables.tf 에서 선언한 변수를 참조
cidr_block = var.vpc_cidr
tags = {
Name = "test"
}
}
# 퍼블릭 서브넷
resource "aws_subnet" "public" {
vpc_id = aws_vpc.vpc.id
cidr_block = var.public_subnet_cidr
availability_zone = var.az_1a
map_public_ip_on_launch = true
tags = {
Name = "test-subnet-public"
}
}
resource "aws_network_interface" "test" {
subnet_id = aws_subnet.public.id
}
# 인터넷 게이트웨이
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.vpc.id
tags = {
Name = "test-igw"
}
}
# Route table
resource "aws_route_table" "public" {
vpc_id = aws_vpc.vpc.id
route {
cidr_block = var.vpc_cidr
gateway_id = "local"
}
}
resource "aws_route" "public" {
route_table_id = aws_route_table.public.id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
resource "aws_route_table_association" "public" {
subnet_id = aws_subnet.public.id
route_table_id = aws_route_table.public.id
}
# EC2
resource "aws_instance" "ad_server" {
instance_type = var.ec2_type
ami = var.ami
subnet_id = aws_subnet.public.id
associate_public_ip_address = true # 퍼블릭 IP 할당
vpc_security_group_ids = [aws_security_group.allow_ssh.id]
iam_instance_profile = aws_iam_instance_profile.ssm_profile.name
key_name = "tokyo-region-key"
tags = {
Name = "test_ec2"
Profile = "SSM_Profile"
}
}
resource "aws_iam_instance_profile" "ssm_profile" {
name = "ssm_ec2_profile"
role = aws_iam_role.ssm_role.name
}
# 보안그룹
resource "aws_security_group" "allow_ssh" {
name = "ssh_sg"
description = "Allow ssh"
vpc_id = aws_vpc.vpc.id
tags = {
Name = "ssg_sg"
}
}
# 보안그룹 인바운드 룰
resource "aws_vpc_security_group_ingress_rule" "allow_ssh" {
security_group_id = aws_security_group.allow_ssh.id
cidr_ipv4 = "xxx.xxx.xxx.xxx/xx"
to_port = 22
from_port = 22
ip_protocol = "tcp"
}
Terraform 배포
작성한 Terraform 코드는 terraform plan
명령어로 실제로 리소스가 어떻게 생성될 것인지 확인하거나 terraform apply
명령어로 리소스를 실제로 생성하기 위해 배포할 수 있습니다.
# 리소스가 어떻게 생성될지 확인
terraform plan
# 문제가 없다면 실제로 리소스를 생성
terraform apply
끝으로
Terraform 을 사용하여 EC2 서버를 생성해 보았습니다.
본 블로그에서는 단순히 한 대의 EC2를 생성해보았지만 앞으로 더욱 복잡한 환경과 리소스도 테라폼으로 구축할 수 있도록 공부해보고 싶습니다.